import moment from "moment";
import math, { FIXEDINDEX } from "../utils/math";

// 试剂信息
export const getDesignerReagent = ({
  lang,
  langCur,
  getReagentInfoById,
  getReagentUnit,
  designer,
  getDictValuesByKey,
}: any) => {
  const getShapeLabel = (value: string, _langCur: string) => {
    let label = "";
    getDictValuesByKey("reagentFormType").some((item: any) => {
      if (item.value === value) {
        label = item.label;
        if (_langCur === "zhcn") {
          label = item.cnlabel;
        }
        return true;
      }
      return false;
    });
    return label;
  };

  const designerReagentList: any = [];
  const designerReagentTitle: string[] = [
    lang["langname"],
    lang["langabbreviation"],
    lang["langcnname"],
    lang["langformula"],
    lang["langdensity"],
    lang["langpercentage"],
    lang["langmolecularweight"],
    lang["langmeltingpoint"],
    lang["langboilingpoint"],
    lang["langcasno"],
    lang["langslot"],
    lang["langbottleposition"],
    lang["langtype"],
    lang["langvolatile"],
    lang["langviscose"],
    lang["langamount"],
    lang["langMolaramout"],
    lang["langvolume"],
    lang["langweight"],
    lang["langused"],
    `${lang["langused"]} ${lang["langMolaramout"]}`,
    `${lang["langused"]} ${lang["langvolume"]}`,
    `${lang["langused"]} ${lang["langweight"]}`,
    lang["langnote"],
  ];

  const { reagents } = designer;
  if (reagents) {
    const slotReagents = { ...reagents };
    const slots = Object.keys(slotReagents);
    if (slots && slots.length) {
      slots.forEach((slotName: string) => {
        const bottleObj = slotReagents[slotName];
        const bottles = Object.keys(bottleObj);
        if (bottles && bottles.length) {
          bottles.forEach((bottleName: string) => {
            const reagentInfo = bottleObj[bottleName];
            const { reagentId, defaultAmount, mmol, volume, weight } =
              reagentInfo;
            const reagent = getReagentInfoById(reagentId);
            const unit = getReagentUnit(reagentId, lang);
            if (reagent) {
              let usedMmol = null;
              let usedVolume = null;
              let usedWeight = null;
              if (
                volume !== null &&
                defaultAmount.volume !== null &&
                defaultAmount.volume !== undefined
              ) {
                let temp: any = math.format(
                  math.evaluate(`${defaultAmount.volume} - ${volume}`),
                  FIXEDINDEX
                );
                usedVolume = temp - 0;
              }
              if (
                weight !== null &&
                defaultAmount.weight !== null &&
                defaultAmount.weight !== undefined
              ) {
                let temp: any = math.format(
                  math.evaluate(`${defaultAmount.weight} - ${weight}`),
                  FIXEDINDEX
                );
                usedWeight = temp - 0;
              }
              if (
                mmol !== null &&
                defaultAmount.mmol !== null &&
                defaultAmount.mmol !== undefined
              ) {
                let temp: any = math.format(
                  math.evaluate(`${defaultAmount.mmol} - ${mmol}`),
                  FIXEDINDEX
                );
                usedMmol = temp - 0;
              }

              let amount = null;
              let used = null;
              if (reagentInfo.type === 1) {
                amount = defaultAmount.volume;
                used = usedVolume;
              } else if (reagentInfo.type === 2) {
                amount = defaultAmount.weight;
                used = usedWeight;
              }

              const {
                name,
                cnname,
                casno,
                type,
                volatile,
                viscose,
                note,
                formula,
                density,
                mw,
                bp,
                mp,
                abbreviation,
                percentage,
              } = reagent;
              designerReagentList.push({
                name,
                cnname,
                formula,
                density,
                casno,
                mw,
                slotName,
                bottleName,
                type: getShapeLabel(type, langCur),
                volatile,
                viscose,
                amount,
                used,
                note,
                unit,
                bp,
                mp,
                abbreviation,
                percentage,
                defaultAmount,
                usedMmol,
                usedVolume,
                usedWeight,
                unitml: lang["langmlunit"],
                unitmg: lang["langmg"],
                unitmmol: lang["langmmol"],
              });
            }
          });
        }
      });
    }
  }

  return {
    designerReagentList,
    designerReagentTitle,
  };
};

// 获取架子类型
export const getAssignment = ({ allShelf, plate }: any): string => {
  let tempName = "";
  allShelf.some(({ name, rackType }: any) => {
    if (name === plate) {
      tempName = rackType.replace(rackType[0], rackType[0].toUpperCase());
      return true;
    }
    return false;
  });
  return tempName;
};

export const getReactions = ({
  designer,
  getReagentInfoById,
  getEnReagentUnit,
  deck_config,
}: any) => {
  let index = 1;
  const { temperature, reactionTime, updateTime, reactors } = designer;

  let ReactorReagents: any = [];

  // 按照试管名合并下数据
  if (reactors && reactors.length) {
    let tempObj: any = {};
    reactors.forEach((item: any) => {
      if (!tempObj[item.tubeName]) {
        tempObj[item.tubeName] = [];
      }
      tempObj[item.tubeName].push(item);
    });

    let ObjValues = Object.values(tempObj);
    ObjValues.forEach((item: any) => {
      let tempReagents: any = [];
      item.forEach((ritem: any) => {
        const { tubeName, reagentid, from } = ritem;
        const reagentInfo = getReagentInfoById(reagentid);
        const unit = getEnReagentUnit(reagentid);
        if (reagentInfo) {
          const { name, type, volatile, density } = reagentInfo;
          from.forEach(
            ({ mmol, weight, volume, bottleName, slotName }: any) => {
              let amount = null;
              if (ritem.type === 1) {
                amount = volume;
              } else if (ritem.type === 2) {
                amount = weight;
              }
              tempReagents.push({
                name,
                type,
                reagentPlateName: deck_config[slotName].plate,
                reagentPlatePosition: slotName,
                reagentPosition: bottleName,
                reactionPosition: tubeName,
                amount,
                mmol,
                volume,
                weight,
                unit,
                density: density ? density - 0 : "",
                is_volatile: !!volatile ? true : false,
              });
            }
          );
        }
      });
      ReactorReagents.push(tempReagents);
    });
  }

  return {
    tracking_number: moment(updateTime).format("DD/MM/YYYY/hh:mm/") + index,
    reactor_type: "reactor_square_8mL",
    reactor_no: index,
    addition_temperature: temperature,
    reaction_time: reactionTime,
    reaction_temperature: temperature,
    reagents: ReactorReagents,
  };
};

const exportTube = (data: any, bottleInfo: any) => {
  if (!data || !bottleInfo) {
    return {};
  }
  const { name, column, row, bottleList, rackType = "" } = data;
  const { depth, diameter, height, shape, volume } = bottleInfo;
  let ordering: any = [];
  let wells: any = {};

  bottleList.forEach(({ autox, autoy, name, x, y }: any) => {
    ordering.push(name);
    wells[name] = {
      depth,
      height,
      volume,
      shape,
      diameter,
      x: x || autox,
      y: y || autoy,
    };
  });

  let obj = {
    version: 1.0,
    function: rackType,
    name,
    columns: column,
    rows: row,
    ordering,
    wells,
  };

  return obj;
};

export const getDeskReagentConfig = ({
  designer,
  designerWorkbench,
  allShelf,
  allBottle,
}: any) => {
  const { slotShelf, reactorSlotShelf } = designer;

  let deck_config: any = {};
  let tuberackList: any = [];

  let shelfNames: string[] = [];

  const { slotList } = designerWorkbench;
  if (slotList && slotList.length) {
    slotList.forEach((item: any) => {
      const slotName = item.name;
      if (slotShelf[slotName]?.shelf) {
        shelfNames.push(slotShelf[slotName]?.shelf);
      }
      //   if (slotName !== "C3") {
      let plate = slotShelf[slotName]?.shelf;
      let assignment = getAssignment({ allShelf, plate });
      if (!plate) {
        plate = "not_used";
        assignment = "Not_used";
      }

      deck_config[slotName] = {
        plate,
        assignment,
      };
      //   } else {
      //     const Slots = Object.keys(reactorSlotShelf);
      //     // 只有一个槽位可以用
      //     const plate = reactorSlotShelf[Slots[0]].shelf;

      //     deck_config[slotName] = {
      //       plate,
      //       assignment: getAssignment({ allShelf, plate }),
      //     };
      //   }
    });
  }

  shelfNames.forEach((shelfName: string) => {
    let shelfInfo;
    let bottleInfo;
    allShelf.some((item: any) => {
      if (item.name.trim() === shelfName.trim()) {
        shelfInfo = item;
        const { bottleType } = item;
        allBottle.some((bottleItem: any) => {
          if (bottleItem.id === bottleType) {
            bottleInfo = bottleItem;
            return true;
          }
          return false;
        });
        return true;
      }
      return false;
    });
    tuberackList.push(exportTube(shelfInfo, bottleInfo));
  });

  return {
    deck_config,
    tuberackList,
  };
};

export const createReactorExcelData = ({
  plate,
  reagentsort,
  slotreagent,
  getReagentInfoById,
  bottleNames,
  shelfName
}: any) => {
  if (!plate || !reagentsort) {
    return {
      excelHeader: [],
      excelData: [],
    };
  }
  let slotList: any = [];
  if (slotreagent) {
    slotList = slotreagent[plate];
  }

  const reagentNames: string[] = [];
  reagentsort.forEach((id: string) => {
    if (id === "Temp/Time") {
      reagentNames.push(id);
    } else {
      const reagentInfo: any = getReagentInfoById(id);
      if (reagentInfo) {
        const { abbreviation, name, cnname } = reagentInfo;
        let tempName = "-";
        if (abbreviation) {
          tempName = abbreviation;
        } else if (name) {
          tempName = name;
        } else if (cnname) {
          tempName = cnname;
        }
        reagentNames.push(tempName);
      }
    }
  });

  const excelHeader: string[] = [`Reactor (${shelfName})`, "Slot", ...reagentNames];

  const excelData: string[][] = [];
  bottleNames.forEach((name: string) => {
    const reagentList = slotList[name];
    const itemData: string[] = [name, plate];
    if (reagentList && reagentList.length) {
      reagentList.forEach((item: any) => {
        if (!item) {
          itemData.push("");
        } else {
          if (item.reagentid) {
            itemData.push(`${item.amount} ${item.unit}`);
          } else if (item.templature) {
            itemData.push(`${item.templature} oC/${item.time} h`);
          }
        }
      });
    }
    excelData.push(itemData);
  });

  return {
    excelHeader,
    excelData,
  };
};

function processData(data: any) {
  // 处理数组的 null 修剪逻辑
  const trimNulls = (arr: any) => {
    // 检查是否全为 null
    if (arr.every((item: any) => item === null)) return null;

    // 逆序查找最后一个非 null 的位置
    let lastIndex = -1;
    for (let i = arr.length - 1; i >= 0; i--) {
      if (arr[i] !== null) {
        lastIndex = i;
        break;
      }
    }

    return lastIndex === -1 ? null : arr.slice(0, lastIndex + 1);
  };

  //处理对象结构
  const processObject = (obj: any): any => {
    if (Array.isArray(obj)) {
      return trimNulls(
        obj.map((item: any) =>
          typeof item === "object" ? processObject(item) : item
        )
      );
    } else if (obj && typeof obj === "object") {
      const newObj: any = {};
      for (const key in obj) {
        newObj[key] = processObject(obj[key]);
        // 过滤掉值为 null 的键
        if (newObj[key] === null) delete newObj[key];
      }
      return newObj;
    }
    return obj;
  };

  return processObject(data);
}

function parseData(data: string) {
  // 使用正则表达式匹配数值和单位
  const regex = /^\s*(-?\d+(?:\.\d+)?)\s*([^\d\s]+)\s*$/;
  const match = data.match(regex);

  if (match) {
    // 提取数值和单位
    const amount = parseFloat(match[1]);
    const unit = match[2];
    return { amount, unit };
  }

  // 如果匹配失败，返回 null
  return null;
}
export function parseExcelData(data: any) {
  const result: any = {
    names: [],
    list: {},
  };

  // 取data数组第一个
  const tmp_names = data.slice(0, 1);

  // 去掉tmp_names 里的空元素
  tmp_names[0] = tmp_names[0].filter((item: any) => !!item);

  // tmp_names 数组排除前两个
  result.names = tmp_names[0].slice(2);

  let dataObj: any = {
    [data[1][1]]: {},
  };

  for (let i = 0; i < data.length; i++) {
    if (i === 0) {
      continue;
    }
    const tmp = data[i];
    if (!dataObj[tmp[1]][tmp[0]]) {
      dataObj[tmp[1]][tmp[0]] = [];
    }
    for (let j = 0; j < tmp.length; j++) {
      if (j > 1) {
        let parsedValue: any = null;
        const value_string = tmp[j];
        if (value_string) {
          const parts = value_string.split("/");
          if (value_string.indexOf("/") >= 0) {
            // 温度时间
            const tempPart = parts[0].trim();
            const timePart = parts[1].trim();
            const temp = parseFloat(tempPart.replace("oC", ""));
            const time = parseFloat(timePart.replace("h", ""));
            parsedValue = {
              templature: temp,
              time: time,
            };
          } else {
            // 数据
            const tmp_data = parseData(value_string);
            if (tmp_data) {
              parsedValue = tmp_data;
              parsedValue.reagent = tmp_names[0][j]; // +2 to skip Reactor and Slot
            }
          }
        }

        dataObj[tmp[1]][tmp[0]].push(parsedValue);
      }
    }
  }

  result.list = processData(dataObj);
  return result;
}

export function replaceReagentIds(data: any, dict: any) {
  // 创建名称到ID的映射表
  const reagentMap = new Map(dict.map((item: any) => [item.name, item.id]));

  // 深拷贝数据
  const result = JSON.parse(JSON.stringify(data));

  // 递归处理数据
  function processEntry(obj: any): any {
    if (Array.isArray(obj)) {
      return obj.map((item: any) => {
        if (item && typeof item === "object") {
          return processEntry(item);
        }
        return item;
      });
    }

    if (obj && typeof obj === "object") {
      // 处理reagent字段
      if ("reagent" in obj && reagentMap.has(obj.reagent)) {
        obj = {
          ...obj,
          reagent: reagentMap.get(obj.reagent),
        };
      }

      // 处理嵌套对象
      for (const key in obj) {
        obj[key] = processEntry(obj[key]);
      }
    }
    return obj;
  }

  return processEntry(result);
}

export function getFileNameWithoutExtension(fileName: string) {
  const lastDotIndex = fileName.lastIndexOf(".");
  if (lastDotIndex === -1) {
    return fileName;
  }
  return fileName.substring(0, lastDotIndex);
}
